package com.derbysoft.ota.application.service;

import static org.junit.Assert.assertEquals;

import javax.xml.bind.JAXBElement;

import org.junit.Test;

import util.Jaxb2MarshallerHolder;

import com.derbysoft.ota.application.service.impl.StagingServiceImpl;
import com.derbysoft.ota.application.util.Jaxb2Marshallers;
import com.derbysoft.ota.interfaces.protocol._2009a.HotelResRequestType;
import com.derbysoft.ota.interfaces.protocol._2009a.OTACancelRQ;
import com.derbysoft.ota.interfaces.protocol._2009a.OTACancelRS;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelAvailRQ;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelAvailRS;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelSearchRQ;
import com.derbysoft.ota.interfaces.protocol._2009a.OTAHotelSearchRS;


public class StagingServiceTest {
	
	private StagingService service = new StagingServiceImpl(Jaxb2MarshallerHolder.get());
	
	@Test(expected = NullPointerException.class)
	public void nullCorrelationID() {
		service.getAvail(new OTAHotelAvailRQ());
	}
	
	@Test(expected = IllegalArgumentException.class)
	public void invalidCorrelationID() {
		OTAHotelAvailRQ availRQ = new OTAHotelAvailRQ();
		availRQ.setCorrelationID("0");
		service.getAvail(availRQ);
	}

	@Test(expected = IllegalArgumentException.class)
	public void invalidAvailRQ() {
		OTAHotelAvailRQ availRQ = new OTAHotelAvailRQ();
		availRQ.setCorrelationID("1");
		service.getAvail(availRQ);
	}
	
	@Test
	public void avail1() {
		avail("OTA_HotelAvailRQ1.xml", "OTA_HotelAvailRS1.xml");
		avail("OTA_HotelAvailRQ2.xml", "OTA_HotelAvailRS2.xml");
		avail("OTA_HotelAvailRQ3.xml", "OTA_HotelAvailRS3.xml");
	}

	private void avail(String rqXml, String rsXml) {
		marshalledResultEquals(
			unmarshall(rsXml, OTAHotelAvailRS.class), 
			service.getAvail(unmarshall(rqXml, OTAHotelAvailRQ.class))
		);
	}

	@Test
	public void search() {
		doSearching("OTA_HotelSearchRQ1.xml", "OTA_HotelSearchRS1.xml");
		doSearching("OTA_HotelSearchRQ2.xml", "OTA_HotelSearchRS2.xml");
		doSearching("OTA_HotelSearchRQ3.xml", "OTA_HotelSearchRS3.xml");
		doSearching("OTA_HotelSearchRQ4.xml", "OTA_HotelSearchRS4.xml");
	}

	private void doSearching(String rqXml, String rsXml) {
		marshalledResultEquals(
			unmarshall(rsXml, OTAHotelSearchRS.class),
			service.search(unmarshall(rqXml, OTAHotelSearchRQ.class))
		);
	}

	@Test
	public void res() {
		make("OTA_HotelResRQ1.xml", "OTA_HotelResRS1.xml");
		make("OTA_HotelResRQ2.xml", "OTA_HotelResRS2.xml");
		make("OTA_HotelResRQ3.xml", "OTA_HotelResRS3.xml");
		make("OTA_HotelResRQ4.xml", "OTA_HotelResRS4.xml");
		make("OTA_HotelResRQ5.xml", "OTA_HotelResRS5.xml");
	}

	@SuppressWarnings("unchecked")
	private void make(String rqXml, String rsXml) {
		JAXBElement<?> expected = unmarshall(rsXml, JAXBElement.class);
		JAXBElement<HotelResRequestType> rq = unmarshall(rqXml, JAXBElement.class);
		marshalledResultEquals(expected, service.make(rq));
	}

	@Test
	public void cancel() {
		doCancel("OTA_CancelRQ1.xml", "OTA_CancelRS1.xml");
		doCancel("OTA_CancelRQ2.xml", "OTA_CancelRS2.xml");
		doCancel("OTA_CancelRQ3.xml", "OTA_CancelRS3.xml");
	}

	private void doCancel(String rqXml, String rsXml) {
		marshalledResultEquals(
			unmarshall(rsXml, OTACancelRS.class),
			service.cancel(unmarshall(rqXml, OTACancelRQ.class))
		);
	}


	private void marshalledResultEquals(Object o1, Object o2) {
		assertEquals(marshall(o1), marshall(o2));
	}

	private String marshall(Object o) {
		return Jaxb2Marshallers.marshall(Jaxb2MarshallerHolder.get(), o);
	}

	private <T> T unmarshall(String xml, Class<T> expectedType) {
		return Jaxb2Marshallers.unmarshall("ota2009a/xml/staging/" + xml, expectedType);
	}

}
